Skip to content

Add PEC with SLC tutorial#5218

Open
henryzou50 wants to merge 21 commits into
mainfrom
slc-tutorial
Open

Add PEC with SLC tutorial#5218
henryzou50 wants to merge 21 commits into
mainfrom
slc-tutorial

Conversation

@henryzou50

@henryzou50 henryzou50 commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a new tutorial, "Probabilistic error cancellation with shaded lightcones." It is an updated version of the SLC-PEC tutorial from the QDC Challenges 2025 repo: https://github.com/qiskit-community/qdc-challenges-2025/blob/main/day3_tutorials/Track_A/slc_pec/qdc_tutorial_slc.ipynb

Probabilistic error cancellation (PEC) produces unbiased expectation values but at a sampling overhead (γ²) that grows exponentially with circuit noise. Shaded lightcones (SLC) bound each noise term's contribution to the observable so the mitigation budget is spent only where it matters, trading a small bounded residual bias for a large reduction in overhead. The tutorial implements the full PEC+SLC workflow on a 20-qubit mirrored Ising circuit (observable ⟨X₆Z₁₃⟩) using qiskit-addon-slc, samplomatic, NoiseLearnerV3, and the QuantumProgram/Executor classes in Qiskit Runtime, following the four-step Qiskit pattern, and compares full PEC, PEC+SLC, and the unmitigated baseline.

Major changes from the original

  • Updated to released Qiskit Runtime (0.47.0). Migrated off the executor_preview branch. Executor, QuantumProgram, and NoiseLearnerV3 are imported from the top-level qiskit_ibm_runtime; noise-learner options are passed as a plain dict (no NoiseLearnerV3Options). qiskit-addon-slc 0.1.0 is already the latest release, so its pin is kept.
  • Removed hardcoded credentials. Replaced the shared_service (token + instance CRN) and the named QiskitRuntimeService(name="qdc-2025") with a plain QiskitRuntimeService() that reads saved credentials.
  • Runs live, no saved jobs. Removed all saved-job loading (shared_service.job(...) IDs and the load_cached_* branches); the noise learner and Executor execute live, with the noise-learning job tagged TUT_SLC.
  • Noise-learning depth tuned. The deepest NLv3 layer_pair_depths value is set to half the circuit's two-qubit-layer depth, so the total learned depth matches the depth of the circuit being mitigated (computed programmatically from the boxed circuit). This noticeably improves the learned model.
  • Dropped the cluster-resources demonstration. Removed the committed merged_bounds_cluster.pickle load; local_scales and the execution now use the live, laptop-computed merged_bounds, and the sampling-overhead plot compares full PEC vs PEC+SLC only (with autoscaling y-limits).
  • Cleanup. Removed logging.basicConfig INFO logging (kept the multiprocessing set_start_method / OMP_NUM_THREADS setup SLC requires), stripped INFO-log and local-path stream outputs, and converted in-page anchor links to plain references.
  • Reformatted to the tutorial template. Added title/description frontmatter, learning outcomes, prerequisites, adapted background (relative doc links, committed AVIF figures), requirements, setup, and next steps. The small-scale simulator section is kept but explains why simulation is skipped (SLC mitigates learned hardware noise).

Files

  • New: docs/tutorials/pec-with-shaded-lightcones.ipynb + images under public/docs/images/tutorials/pec-with-shaded-lightcones/ (3 background schematics and the extracted cell outputs).
  • Registered in docs/tutorials/_toc.json and docs/tutorials/index.mdx (Error mitigation section), added to the notebook-CI exclude list in scripts/config/notebook-testing.toml, and given an owner in qiskit_bot.yaml.

Results / testing

Ran on IBM Quantum hardware (ibm_boston), tox -e lint, the notebook normalizer, spelling, and internal-link checks all pass.

Adapt the SLC-PEC tutorial from the QDC Challenges 2025 repo [1] into a
documentation tutorial, updated for the released Qiskit Runtime and
restructured to follow the standard tutorial template.

New files:
- docs/tutorials/pec-with-shaded-lightcones.ipynb
- public/docs/images/tutorials/pec-with-shaded-lightcones/ (3 background
  schematics + extracted cell outputs)

Registered in docs/tutorials/_toc.json and docs/tutorials/index.mdx under
"Error mitigation", excluded from notebook CI in
scripts/config/notebook-testing.toml (consistent with other tutorials), and
given an owner in qiskit_bot.yaml.

Important changes and updates from the original [1]:

- API: migrated off the `executor_preview` branch to the released
  qiskit-ibm-runtime 0.47.0. `Executor`, `QuantumProgram`, and
  `NoiseLearnerV3` are imported from the top-level package, and noise-learner
  options are passed as a plain dict instead of `NoiseLearnerV3Options`.
  (qiskit-addon-slc 0.1.0 is already the latest release, so its pin is kept.)

- Credentials: replaced the hardcoded `shared_service` (token + `instance`
  CRN) and the named `QiskitRuntimeService(name="qdc-2025")` with a plain
  `QiskitRuntimeService()` that reads saved credentials.

- Live execution: removed all saved-job loading (the `shared_service.job(...)`
  IDs and the `load_cached_*` branches). The noise learner and Executor now
  run live, and the noise-learning job is tagged `TUT_SLC`.

- Noise-learning depth: set the deepest NLv3 `layer_pair_depths` value to half
  the circuit's two-qubit-layer depth, so the total learned depth matches the
  depth of the circuit being mitigated (computed programmatically from the
  boxed circuit). This noticeably improves the learned model for mitigation.

- Dropped the cluster-resources demonstration: removed the committed
  `merged_bounds_cluster.pickle` load. `local_scales` and the execution now
  use the live laptop-computed `merged_bounds`, and the sampling-overhead plot
  compares full PEC against PEC+SLC only. Its hardcoded y-limits were removed
  so it autoscales to the run's values.

- Cleanup: removed the `logging.basicConfig` INFO logging (kept the
  multiprocessing `set_start_method`/`OMP_NUM_THREADS` setup that SLC needs),
  and stripped INFO-log and local-path stream outputs.

- Structure: reformatted to the tutorial template (title/description
  frontmatter, learning outcomes, prerequisites, adapted background with
  relative doc links and committed AVIF figures, requirements, setup, next
  steps). The small-scale simulator section is kept but explains why
  simulation is skipped (SLC mitigates learned hardware noise). Converted
  in-page anchor links to plain references.

This run was executed on ibm_boston. The PEC+SLC results are not as strong as
the original QDC run: full PEC has a very high sampling overhead
(gamma^2 ~ 1.8e4), and although PEC+SLC reduces this ~17x and far outperforms
plain PEC, it does not fully settle within the 10% bias band in the
randomizations shown. The commentary has been updated to reflect this, and the
figures will likely be regenerated on a rerun (for example, with more
randomizations) before final publication.
@henryzou50 henryzou50 requested a review from a team June 4, 2026 18:58
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@qiskit-bot

Copy link
Copy Markdown
Contributor

One or more of the following people are relevant to this code:

  • @nathanearnestnoble

Rerun the tutorial on hardware and refresh the results commentary to
match the new data:

- Update executed outputs: full PEC sampling cost (gamma^2) 1.8e4 -> 8.7e4,
  PEC+SLC sampling cost 1.1e3 -> 4.2e3, plus minor shifts in shots-kept
  fractions for noise learning (0.86 -> 0.85) and post-selection (~25.7%
  -> ~26.7%).
- Revise the results discussion: SLC now reduces overhead ~20-fold (was
  ~17-fold), and PEC+SLC settles in the physical region near the exact
  value (previously it converged above 1, in the unphysical region).
- Fix a broken sentence in the "Box the circuit" section ("the SLC
  workflow the use of" -> "the SLC workflow requires the use of").
Switch the hardware example from ibm_boston to ibm_fez and refresh all
cell outputs and the results commentary to match the new run (unmitigated
~0.2, full PEC gamma^2 ~4.2e3, PEC+SLC gamma^2 ~5.9e2 at ~10% residual
bias, ~7-fold overhead reduction).

Make the noise-learning depth schedule robust: keep a fixed candidate
schedule [1, 2, 4, 8, 12, 16, 24, 32, 40, 48], drop any candidate that
exceeds the circuit's depth, and always cap the deepest value at
max_layer_pair_depth so we never learn deeper than the circuit being
mitigated. Previously sorted({1, 2, 4, 8, 12, 16, max_layer_pair_depth})
could include hardcoded depths (e.g. 12, 16) beyond the circuit when
max_layer_pair_depth was small.

On counting two-qubit layers: we count InjectNoise-annotated boxes rather
than QuantumCircuit.depth(num_qubits == 2). After boxing, circuit data are
full-width BoxOp instructions, so a num_qubits == 2 filter matches nothing;
the boxing pass tags exactly one InjectNoise annotation per two-qubit layer,
so counting those boxes gives precisely the layer depth NLv3 will learn.
Added an inline comment to this effect.
Measure the two-qubit-layer depth with isa_circuit.depth(num_qubits == 2)
instead of counting InjectNoise-annotated boxes, and drop the now-unused
get_annotation / InjectNoise imports. After boxing, two-qubit gates are hidden
inside full-width BoxOp instructions, so a num_qubits == 2 filter on
boxed_circuit matches nothing and QuantumCircuit.depth does not recurse into
boxes; the pre-boxed ISA circuit gives the true 2q critical-path depth, halved
for layer pairs. Value unchanged for this circuit (depth_2q = 40 -> 20).

Refresh outputs from a new ibm_fez run and update the results commentary to
match (full PEC gamma^2 ~2.4e3, PEC+SLC gamma^2 ~3.7e2, ~6-fold reduction,
SLC settling near 0.9 within the ~10% residual-bias bound).
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
Comment thread docs/tutorials/pec-with-shaded-lightcones.ipynb Outdated
henryzou50 and others added 3 commits June 25, 2026 20:26
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
henryzou50 and others added 2 commits June 25, 2026 20:27
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
henryzou50 and others added 3 commits June 25, 2026 20:28
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
henryzou50 and others added 3 commits June 25, 2026 20:29
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
henryzou50 and others added 3 commits June 25, 2026 20:30
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
Co-authored-by: abbycross <across@us.ibm.com>
@henryzou50

Copy link
Copy Markdown
Collaborator Author

Appreciate the review and suggestions @abbycross. I just finished applying them!

@abbycross abbycross left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@abbycross abbycross added this pull request to the merge queue Jun 26, 2026
@abbycross abbycross removed this pull request from the merge queue due to a manual request Jun 26, 2026
@abbycross

Copy link
Copy Markdown
Collaborator

@nathanearnestnoble do you want to do a review before we merge?

@mrossinek mrossinek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work on this! This already looks great, below are mostly nit-picks and a few more general comments.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trade a bounded residual bias for lower sampling overhead

Technically speaking, it is possible to retain a zero-bias estimate and still reduce the sampling overhead (geometric lightcone). But it is true that the shading is what allows you a further trading. Might be worth pointing out though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that this gets mentioned further down, but am wondering if this single line needs some adjusting. Up to you

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to learn layer noise with NoiseLearnerV3 and inject anti-noise through samplomatic and the Executor primitive

I suggest typesetting Executor as code to be consistent with the typesetting of NLv3 and samplomatic

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that upper-bounds the susceptibility of the observable to that error.

Very much a nit-pick, but: we are bouding the susceptibility of the observable's expectation value to that error. In the backward bounds case, that also depends on the chosen initial state of the circuit (all-zero in typical workflows and sufficient for the purposes of this tutorial).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case of our mirrored Ising circuit

I find it a bit odd, that the first time this gets mentioned is during the Post-processing overview. The phrasing suggests that this has already been established before but it has not.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pip install 'qiskit-addon-utils'

Nit-pick: this is the only dependency that is typeset with surrounding quotes although that is not strictly necessary

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Predict to-be-learned noise-model Paulis

Is the explanation of generate_noise_model_paulis really clear? To me it makes sense, but I have gotten feedback offline that this can be fairly confusing for someone new to the concept of noise learning. Would be good to get a sanity check on this section being clear.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slc_atol = 1e-8
slc_eigval_max_qubits = 18
slc_evolution_max_terms = 1000
slc_num_processes = 8
slc_timeout = 60

I think it is improtant that these settings be explained in more detail.

Also:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which tracks how the observable spreads backward through the circuit and uses that spread to place upper bounds on the effect of each noise operator

I think it may be useful to be more concrete and refer to the bound exploiting the limited speed at which information can spread.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can further tighten the bounds by accounting for lightcone limitation. In principle, this gives us a smoother transition from the computed bounds to the trivial bounds set forth after the timeout was reached. Here, the effect is not as visible because the lightcones have already reached the edge of the circuit.

This feels a bit redundant to the previous paragraph.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point to switch from forward to backward bounds depends on the learned noise rates.

Yes, but at this point our noise_model_rates are initialized to None which assumes even rates and is meant just as a preview. This should be clarified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants